/*
 * CAudioRender.h
 *
 *  Created on: 2017年3月16日
 *      Author: chuanjiang.zh
 */

#ifndef CAUDIORENDER_H_
#define CAUDIORENDER_H_

#include "AudioRender.h"
#include "TimePoint.h"
#include "SDL.h"
#include "TCriticalSection.h"
#include "AVFrameQueue.h"

namespace av
{

class CAudioRender: public AudioRender
{
public:
	CAudioRender();
	virtual ~CAudioRender();

	virtual int open(int channels, int sampleRate, int sampleFmt);

	virtual void close();

	virtual bool isOpen();

	virtual int play();

	virtual int pause();

	virtual void stop();

	virtual bool isPaused();

	virtual int write(AVFrame* frame);

	virtual void flush();

	/**
	 * 获取音量
	 * @return
	 */
	virtual float getVolume();

	/**
	 * 设置音量
	 * @param vol   取值范围：[0.0,1.0]
	 * @return
	 */
	virtual int setVolume(float vol);

	virtual bool isMute();

	virtual int setMute(bool muted);


	static void sdlAudioCallback(void* userdata, Uint8* stream, int len);
	void audioCallback(Uint8* stream, int len);


protected:
    int mixFrame(AVFrame* pFrame, Uint8* buffer, int size, int vol, bool& consumed);
    int mixFrame(AVFrame* pFrame, int pos, Uint8* buffer, int size, int vol, bool& consumed);
    int mixLastFrame(Uint8* buffer, int size, int vol);

    void saveFrame(AVFrame* pFrame, int pos);
    void clearFrame();

    int resample(AVFrame* inFrame, AVFrame* outFrame);

    int64_t getClock();

    AVFrame*    fetchFrame();

	AVFrame* flushResample();

	int chooseSampleFormat(int fmt, AVSampleFormat& outFmt);

	void pauseDevice(bool toPause);

protected:
	TimePoint	m_timePoint;

	SDL_AudioDeviceID   m_audioDev;
	SDL_AudioSpec       m_audioSpec;

	comn::CriticalSection	m_cs;

    AVFrameQueue	m_frameQueue;
    AVFrame*    m_curFrame;
    int         m_framePos;
    bool 		m_playing;

    SwrContext*		m_swrContext;
	AVSampleFormat  m_inFormat;
	AVSampleFormat	m_outFormat;
	int		m_resampleRate;

    int		m_volume;
    bool 	m_muted;

    TimePoint	m_curPoint;
	AVRational  m_scale;

};


} /* namespace av */

#endif /* CAUDIORENDER_H_ */
